/*
  方法装饰器使用起来是一样的  
    工厂模式下  外层的函数接收的是装饰器传参  内层函数传递三个参数  分别是 原型对象  方法名  方法描述
*/

function funMs(params: string) {
  return function (target: any, functionName: string, desc: any) {
    console.log(params) //  Jimmy
    console.log(target) //  funclass { getmoney: [Function] }
    console.log(functionName) //  getmoney
    console.log(desc) //  { value: [Function],writable: true,enumerable: true,configurable: true } 就是这个方法的一些属性特征
    target.run = function (): void {
      console.log('我通过方法修饰器修改了方法的数据')
      console.log('nowTarget', target) // nowTarget funclass { getmoney: [Function], run: [Function] }
    }
    // console.log('NowTarget', target)
  }
}

console.log('////////////////////////////////////')

class funclass {
  constructor(public name: string, private money: number) {}
  @funMs('Jimmy')
  getmoney(): void {
    console.log(`${this.name}的余额为${this.money}`)
  }
}

let funclass1: any = new funclass('Jimmy', 100)
funclass1.getmoney()
funclass1.run() // 我通过方法修饰器修改了方法的数据

/*
  方法参数修饰器  - -  这个使用的比较少
*/
function params1(params: string): any {
  return function (target: object, functionName: string, desc: any) {
    console.log(params) //Jimmy
    console.log(target) // funparams { getData: [Function] }
    console.log(functionName) //  getData
    console.log(desc) //  0
  }
}

class funparams {
  constructor(public name: string, private money: number) {}
  getData(@params1('jimmy') status: boolean): void {
    console.log(`${this.name}的余额为${this.money}`)
  }
}

/*
  方法参数修饰器在工厂模式下  第一个函数可以传递参数  嵌套的函数就是第一个参数时 targer原型对象  第二个参数时方法名  第三个参数是修饰器修饰的参数所传递的值
*/

/*
  修饰器的执行顺序
*/

function classXs1(params: any): any {
  return function () {
    console.log('我是类修饰器1')
  }
  // console.log('我是类修饰器1')
}
function classXs2(target: any): any {
  return function () {
    console.log('我是类修饰器2')
  }
}

function funXs1(params: any): any {
  return function () {
    console.log('我是方法饰器1')
  }
}
function funXs2(params: any): any {
  return function () {
    console.log('我是方法饰器2')
  }
}
function attrXs1(params: any): any {
  return function () {
    console.log('我是属性饰器1')
  }
}
function attrXs2(params: any): any {
  return function () {
    console.log('我是属性饰器2')
  }
}
function paramsXs1(): any {
  return function () {
    console.log('我是参数饰器1')
  }
}
function paramsXs2(): any {
  return function () {
    console.log('我是参数饰器2')
  }
}

@classXs1('Jimmy')
@classXs2('Jimmy')
class speedTest {
  @attrXs1('Jimmy')
  @attrXs2('Jimmy')
  public name: string = 'Jimmy'
  public money: number = 50
  @funXs1('Jimmy')
  @funXs2('Jimmy')
  getData(@paramsXs1() otherName: string, @paramsXs2() allcount: number) {
    console.log(`${this.name}的余额是${this.money}`)
  }
}

/*
  我是属性饰器2
  我是属性饰器1
  我是参数饰器2
  我是参数饰器1
  我是方法饰器2
  我是方法饰器1
  我是类修饰器2
  我是类修饰器1
  
  由以上的结果可以得出结论：
    1 执行顺序： 属性装饰器>参数装饰器>方法装饰器>类装饰器
    2 装饰器的执行顺序是从后向前执行的  也就是说如果装饰器相同的话  写在后面的装饰器会先被执行

*/
